var roleStatusMap = {       
    'DEAD'   : 0,  //死亡
    'NORMAL' : 1,  //正常
    'CONFUSE': 2,  //魅惑
    'SLEEP'  : 3,  //睡眠
};

var defRespMap = {      
    'MISS' : 2,   //闪避
    'CRIT' : 3,   //暴击
    'BLOCK': 4,   //格挡
    'REBOUND' : 5,//反弹
};

var batModMap = {   
    'DUPLICATE' : 0,   //副本                 
    'TOWER'     : 1,   //勇闯重楼         
    'KILL'      : 2,   //过关斩将       
    'PVP'       : 3,   //
    'TOMB'      : 4,   //古墓宝藏
    'DIGTREASURE' : 5, // 地下宝藏
    'MYBATTLE'  : 6,   // 个人战役
};

var searchSequence = {
    '0' : [0,3,6,1,4,7,2,5,8],
    '1' : [1,4,7,0,3,6,2,5,8],
    '2' : [2,5,8,1,4,7,0,3,6],
};

var rowSequence = {
    '0' : [0, 1, 2], // row0
    '1' : [3, 4, 5], // row1
    '2' : [6, 7, 8], // row2
}

var colSequence = {
    '0' : [0, 3, 6], // column0
    '1' : [1, 4, 7], // column1
    '2' : [2, 5, 8], // column2
}

var skillEffectBufs = ['rehurt','atktransdef','sleep','improveatk','confuse',];
var petSkillEffectBufs = ['improvehurt'];

// BUF层次等级
var BufLayerLevel = {
    'NORMAL'    :0,     // 普通
    'STICK'     :1,     // 不可移除
}

// 部队状态
var RoleStatus = {
    'Action': 1,         // 本回已出手
}

//行为类型
var ActionType = {
    'Default': 0,       // 默认
    'Pre': 1,           // 战前处理
}

function Fighter(){
    this.id = 0;
    this.userLevel = 0;                          // 玩家等级
    this.roles = {};
    this.team = {'0':0,'1':0,'2':0,'3':0,'4':0,'5':0,'6':0,'7':0,'8':0};
    this.healthBreakable = true;                 // 血量上限是否可突破(可突破的红颜加血将影响血量上限)
    this.teamHealth = 0;                         // 队伍总血量
    this.teamFightForce = 0;                     // 队伍总战斗力
    this.alive = 0;                              // 存活英雄数量
    this.type = null;                            // 战斗对象的类型(user/monster)
    this.isAttacker = 0;                         // 是否为攻击方(0/1)
    this.isWin = 0;                              // 是否胜利(0/1)
    this.alivePosArr = [];                       // 未死英雄的位置数组
    this.total = 0;                              // 总的英雄数目
    this.headpic = '';                           // 头像
    this.name = '';                              // 名字
    this.specialRoleName = '';                   // 本命武将名字 
    this.pet = {                                 // 神兽
        level : 1,                               // 神兽等阶
        skills : [],                             // 技能顺序
        skillLevels:{},                          // 技能等级
    };

    this.rolePoses = {                           // 英雄ID : 位置Pos
        /*rid:pos*/ 
    };                        
    this.bossType = '';                          // BOSS类型
    this.escapes = {};                           // 可重生的武将列表,{$pos:health}

    /*
     * 以下是可选属性
    this.damageFactor = 1;                       // 受到的伤害系数
    */
}

Fighter.prototype = { 
    initWithPlayer : function(player, bossType, ignoreCalTeamRoleAttr, baseCityAddAttackType){
        var user = player.user;
        this.id = player.uid;
        this.headpic = user.info.headpic;
        this.name = user.info.un;
        this.bossType = bossType;
        
        if (!ignoreCalTeamRoleAttr) {
            player.calculateTeamRoleAttr();
        }
        
        var inspireRate = 0;
        if( bossType == 'league_boss') { //团BOSS战时鼓舞次数
            inspireRate = user.boss ? user.boss.inspire*gConfGlobal.LeagueBossInspireAttack : 0;
        }else if( bossType == 'world_boss') { //世界BOSS
            inspireRate = user.world_boss ? user.world_boss.inspire*gConfGlobal.WorldBossInspireAttack : 0;
        }else if( bossType == 'year_boss' ) { //年兽 BOSS
            inspireRate = user.activity.year_boss ? user.activity.year_boss.inspire*gConfGlobal.YearBossInspireAttack : 0;
        }

        var baseCityAddRate = 0; //团体战时, 在基地一方攻击加成
        if ('league_war' == baseCityAddAttackType) {
            baseCityAddRate = gConfGlobal.LeagueWarBaseCityAttackAdd;
        } else if ('battle_world' == baseCityAddAttackType) {
            baseCityAddRate = gConfGlobal.BattleWorldBaseCityAttackAdd;
        }
        
        var team = user.team;
        var roles = user.role;
        var attrs = player.roleAttrs;
        for (var pos in team) {
            var rid = user.team[pos];
            if (rid) {
                this._initPlayerRole(pos, roles[rid], attrs[rid]);
            }
        } 

        if (bossType) {
            // 当打boss时貂蝉不能减BOSS的血量
            this.SpecRoleOfDiaoChan = 0;
        }

        this.addAttackBeforeFight(inspireRate + baseCityAddRate);
        this._initPlayerPet(player);
        
        this.type = 'user';
        this.total = this.alive;
        this.userLevel = user.status.level; 
        this.specialRoleName = user.special_role ? user.special_role.name : '';
    },

    initWithMonster : function(batMod, id, battle){
        this.id = id;
        var boss = gConfMonster[battle.Boss];
        this.headpic = boss.URL; 
        this.name = boss.Name;

        for( var pos = 0; pos < 9; pos++){
            var rid = battle['Pos'+pos];

            if (rid) {
                this._initMonsterRole(pos, gConfMonster[rid]);
            }
        }

        this.pet = {
            'level' : battle.PetLevel ? battle.PetLevel : 1, 
            'skills' : battle.PetSkills, 
            'skillLevels' : battle.PetSkillLevels,
        }

        this.type = 'monster';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = battle.UserLevel; 

        this.specialRoleName = '';
    },

    initWithTroopMatch : function(id, conf){
        this.id = id;
        this.headpic = conf.headpic;
        this.name = conf.name;

        for( var pos = 0; pos < 9; pos++){
            var rid = conf.team[pos];

            if (rid) {
                this._initMonsterRole(pos, gConfTroopMatchRole[rid]); 
            }
        }
        
        this.type = 'monster';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = 1;
    },

    initWithSmashLand: function(player) {
        player.calculateTeamRoleAttr();
        var user = player.user;
        var smashLand = user.smashland;

        this.id = player.uid;
        this.headpic = user.info.headpic;
        this.name = user.info.un;
      
        var team = smashLand.team;
        var roles = user.role;
        var attrs = player.roleAttrs;

        for (var pos in team) {
            var rid = team[pos];
            var curAttr = smashLand.attrs[rid]; 
            var attr = clone(attrs[rid]);
            
            attr.initHealth = curAttr.init_health;
            attr.health = curAttr.health;
            attr.morale = curAttr.morale;

            this._initPlayerRole(pos, roles[rid], attr);
        }
        this._initPlayerPet(player);
        
        this.healthBreakable = false;
        this.type = 'user';
        this.total = this.alive;
        this.userLevel = user.status.level; 
        this.specialRoleName = user.special_role ? user.special_role.name : '';
    },

    /**
     * 初始化平乱怪物
     * @param player
     * @param insurgency
     * @param id
     */
    initWithInsurgencyMonster: function(player, insurgency, teamId){
        // 取怪物阵形配置
        var monsterTeam = gConfInsurgencyTeam[teamId];
        var user = player.user;

        var boss = gConfMonster[monsterTeam.Boss];
        this.headpic = boss.URL;
        this.name = boss.Name;

        // 计算属性倍率
        var factor = +gConfGlobal.InsurgencyMonsterFactor / 100;
        var monsterAttrs = this._mapNpcTeamMonsterFromPlayer(player, monsterTeam, factor);
        var monsterCount = Object.keys(monsterAttrs).length || 1;

        // 初始化怪物武将
        var initHealth = Math.max(1, Math.floor(insurgency.init_health / monsterCount));
        var health = Math.max(1, Math.floor(insurgency.health / monsterCount));
        for (var pos=0; pos < 9; ++pos) {
            var monsterId = monsterTeam["Pos" + pos];
            if (!monsterId) {
                continue;
            }

            var attr = monsterAttrs[monsterId];
            if (!attr) {
                continue;
            }

            attr.initHealth = initHealth;
            attr.health = health;

            this._initMonsterRole(pos, gConfMonster[monsterId], attr);
        }

        // 初始化神兽
        this._initPlayerPet(player);

        this.healthBreakable = false;
        this.type = 'monster';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = player.user.status.level;

        this.specialRoleName = '';
    },

    /**
     * 初始化金矿协助怪物
     * @param player
     * @param id    怪物配置ID
     * @param _initHealth    初始血量
     * @returns {number}
     */
    initWithAssistMineMonster: function(player, id, _initHealth){
        // 取怪物阵形配置
        var monsterTeam = gConfAssistMineTeam[id || 1];
        var user = player.user;

        var boss = gConfMonster[monsterTeam.Boss];
        this.headpic = boss.URL;
        this.name = boss.Name;

        // 计算属性倍率
        var factor = +gConfGlobal.AssistMineMonsterFactor / 100;
        var monsterAttrs = this._mapNpcTeamMonsterFromPlayer(player, monsterTeam, factor);
        var monsterCount = Object.keys(monsterAttrs).length || 1;

        // 初始化怪物武将
        var initHealth = Math.floor(_initHealth / monsterCount);
        var health = initHealth;
        for (var pos=0; pos < 9; ++pos) {
            var monsterId = monsterTeam["Pos" + pos];
            if (!monsterId) {
                continue;
            }

            var attr = monsterAttrs[monsterId];
            if (!attr) {
                continue;
            }

            attr.initHealth = initHealth;
            attr.health = health;

            this._initMonsterRole(pos, gConfMonster[monsterId], attr);
        }

        // 初始化神兽
        this._initPlayerPet(player);

        this.healthBreakable = false;
        this.type = 'monster';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = player.user.status.level;

        this.specialRoleName = '';
    },

    initWithSmashLandMonster: function(player, battle, factor) {
        var user = player.user;

        var boss = gConfMonster[battle.Boss];
        this.headpic = boss.URL; 
        this.name = boss.Name;

        var smashLand = user.smashland;
        var monsterAttrs = this._mapNpcTeamMonsterFromPlayer(player, battle, factor);
        var monsterCount = Object.keys(monsterAttrs).length || 1;

        // 初始化武将
        var initHealth = Math.max(Math.floor(smashLand.enemy_attr.init_health/monsterCount), 1);
        var health = Math.max(Math.floor(smashLand.enemy_attr.health/monsterCount), 1);
        for (var pos = 0; pos < 9; ++pos) {
            var monsterId = battle['Pos'+pos];
            if (!monsterId) {
                continue;
            }

            var attr = monsterAttrs[monsterId];
            if (!attr) {
                continue;
            }

            attr.initHealth = initHealth;
            attr.health = health;

            this._initMonsterRole(pos, gConfMonster[monsterId], attr);
        }

        this._initPlayerPet(player);

        this.healthBreakable = false;
        this.type = 'monster';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = user.status.level; 

        this.specialRoleName = '';
    },

    /**
     * 英雄志
     * @param battle
     */
    initWithHeroLogMonster: function(battle){
        var boss = gConfMonster[battle.Boss];
        this.headpic = boss.URL;
        this.name = boss.Name;

        for( var pos = 0; pos < 9; pos++){
            var rid = battle['Pos'+pos];

            if (rid) {
                this._initMonsterRole(pos, gConfMonster[rid]);
            }
        }

        this.pet = {
            'level' : battle.PetLevel ? battle.PetLevel : 1,
            'skills' : battle.PetSkills,
            'skillLevels' : battle.PetSkillLevels,
        }

        this.type = 'herolog';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = battle.UserLevel;

        this.specialRoleName = '';
    },
    
    initWithChampsBattle: function(player, champsbattle, team) {
        var user = player.user;

        this.id = player.uid;
        this.headpic = user.info.headpic;
        this.name = user.info.un;
      
        var roles = user.role;
        var roleAttrs = user.roleAttrs;
        var curAttrs = champsbattle.attrs;
        for (var pos in team) {
            var rid = team[pos];
            var attr = clone(roleAttrs[rid]);
            var curAttr = curAttrs[rid];
            if (!curAttr) {
                continue;
            }

            if (curAttr.health > 0) {
            	attr.initHealth = curAttr.init_health;
            	attr.health = curAttr.health;
            	this._initPlayerRole(pos, roles[rid], attr);
            }
        }
        this._initPlayerPet(player);
        
        this.healthBreakable = false;
        this.type = 'user';
        this.total = this.alive;
        this.userLevel = user.status.level; 
        this.specialRoleName = '';  	
    },
    
    initWithChampsBattleMonster: function(battle, growthConf) {
        this.id = battle.Id;
        var boss = gConfMonster[battle.Boss];
        this.headpic = boss.URL; 
        this.name = boss.Name;

        for( var pos = 0; pos < 9; pos++){
            var rid = battle['Pos'+pos];

            if (rid) {
                this._initMonsterRole(pos, gConfMonster[rid], null, growthConf);
            }
        }
        
        this.pet = {
            'level' : battle.PetLevel ? battle.PetLevel : 1, 
            'skills' : battle.PetSkills, 
            'skillLevels' : battle.PetSkillLevels,
        }

        this.healthBreakable = false;
        this.type = 'monster';
        this.total = this.alive;
        this.isAttacker = 0;
        this.userLevel = battle.UserLevel; 

        this.specialRoleName = '';
    },
    
    _initPlayerRole: function(pos, role, attr) {
        pos = +pos;
        var rid = role.id;

        var morale = attr.hasOwnProperty('morale') ? attr.morale : 200;
        var health = attr.health || 1;
        var initHealth = attr.initHealth || health;

        var soldierKind = gConfRole[rid]['Soldier'];
        var soldierInit = gConfSoldierInit[soldierKind];
        var skill = +role.skill;

        var posRole = {
            'id' : role.id,                             // 英雄ID
            'xp' : role.xp,                             // 经验
            'level' : +role.level,                      // 英雄等级
            'soldierLevel' : role.soldier_level,        // 兵种等级
            'attack' : attr.attack,                     // 攻击
            'defence' : attr.defence,                   // 武防
            'mdefence' : attr.mdefence,                 // 魔防
            'baseAttack' : attr.attack,                 // 基础攻击
            'baseDefence' : attr.defence,               // 基础武防
            'baseMdefence' : attr.mdefence,             // 基础魔防
            'block' : attr.block,                       // 格挡
            'fortitude' : attr.fortitude,               // 刚毅
            'hit' : attr.hit,                           // 命中
            'unblock' : attr.unblock,                   // 破招
            'critDamage' : attr.critdamage,             // 暴击
            'miss' : attr.miss,                         // 闪避
            'health' : initHealth,                      // 血量
            'skill' : skill,                            // 主动技能ID
            'skillLevels' : role.skill_levels,          // 技能等级对象
            'fightForce' : role.fight_force,            // 战斗力
            'pos' : pos,                                // 英雄位置
            'initPos' : pos,                            // 英雄初始位置
            'soldierKind' : soldierKind,                // 兵种
            'round' : 0,                                // 当前回合数
            'statusArr' : [1, 0, health, 0, morale, 0], // 战斗状态 
            'bufs'   : {},                              // 技能buf
            'skills' : {},                              // 英雄拥有的技能buf集
            'initHit': soldierInit.Hit,                 // 初始命中几率
            'initMiss': soldierInit.Miss,               // 初始闪避几率
            'initBlock' : soldierInit.Block,            // 初始格挡几率
            'initUnblock' : soldierInit.Unblock,        // 初始破招几率
            'initCritDamage' : soldierInit.Critdamage,  // 初始暴击几率
            'initFortitude' : soldierInit.Fortitude,    // 初始刚毅
            'god':+role.god || 0,                       // 神将等级
            'wing':role.wing || 0,                      // 羽翼等级
            'escaped':false,                            // 是否已经复活
        };

        if (role.star) {
            var restrainAttrs = gConfRuntime.RoleStarRestrainAttrs[soldierKind][role.star];
            objectForEach(restrainAttrs, function(key, value) {
                posRole[key] = value;
            });
        }

        for (var skillId in role.skill_levels) {
            skillId = +skillId;
            if (gIsStandSkill(skillId) && (skill != skillId) && (gSoldierKindMap.BEAUTY != soldierKind)) {
                continue;
            }

            var skillLevel = role.skill_levels[skillId];
            var skillKind = gGetSkillKind(soldierKind, skillId);
            var skillEffect = gConfSkillEffect[skillKind][skillId][skillLevel];
            if ((skill != skillId) && (1 == skillEffect.Type)) {
                continue; 
            }

            posRole.skills[skillEffect['Effect']] = {
                'param' : skillEffect['Param'],
                'damage' : skillEffect['Damage'],
                'round' : skillEffect['Round'],
                'isSelf' : skillEffect['IsSelf'],
                'isActive' : (skillEffect['Type'] == 1 ? 1:0 ), //是否主动技能
            };   
        }
        
        // 是否拥有邪武将, 觉醒达到2级开启专属技能
        if(role.god >= 2) {
            var roleIndex = gSpecRoleIndex[rid];
            this['SpecRoleOf'+roleIndex] = rid;
        }
        
        //星座属性
        var horoscope = role.horoscope;
        if (horoscope) {
            var horoscopeAttrs = horoscope.attrs;

            var restrains = horoscopeAttrs.restrain;
            if (restrains) {
                objectForEach(restrains, function(key, value) {
                    addAttrValue(posRole, 'Restrain' + key, value);
                });
            }
            
            var roleSkills = posRole.skills;
            var skills = horoscopeAttrs.skill;
            if (skills) {
                objectForEach(skills, function(name, values) {
                    var roleSkill = roleSkills[name];
                    if (roleSkill) {
                        roleSkill.param += values.param || 0;
                        roleSkill.damage += values.damage || 0;
                    }
                });
            }

            if (horoscopeAttrs.spec) {
                posRole.horoscope = horoscopeAttrs.spec;
            }
        }


        this.roles[pos] = posRole;
        this.rolePoses[rid] = pos;
        this.team[pos] = rid;
        this.teamHealth += health;
        this.teamFightForce += posRole.fightForce;
        this.alive++;
        this.alivePosArr.push(pos);
    },

    _initMonsterRole: function(pos, role, attr, growth) {
        pos = +pos;
        var rid = role.Id;
        var eid = role.EqualRole;
        var level = role.Level;
        var soldierKind = role.Soldier;
        var god = role.God || 0;
        var star = role.Star || 0;

        if (!attr) {
            attr = {
                'attack': role.Attack, 
                'defence': role.Defence,
                'mdefence': role.MagicDefence,
                'health': role.Health,
                'fortitude': role.Fortitude,
                'hit': role.Hit,
                'unblock': role.Unblock,
                'block' : role.Block,
                'critdamage': role.Critdamage,
                'miss': role.Miss,
                'fight_force': role.FightForce,
            }
        } else {
            god = Math.min(god, attr.god||0);
            star = Math.min(star, attr.star||0);
        }
        
        if (growth) {
            var healthFactor = +growth.HealthFactor;
            if (healthFactor) {
                attr.health = Math.ceil(attr.health * healthFactor);
            }

            var defenceFactor = +growth.DefenceFactor;
            if (defenceFactor) {
                attr.defence = Math.ceil(attr.defence* defenceFactor);
                attr.mdefence = Math.ceil(attr.mdefence * defenceFactor);
            }

            var attackFactor = +growth.AttackFactor;
            if (attackFactor) {
                attr.attack = Math.ceil(attr.attack * attackFactor);
            }

            var extFactor = +growth.ExtFactor;
            if (extFactor) {
                attr.fortitude = Math.ceil(attr.fortitude * extFactor);
                attr.hit = Math.ceil(attr.hit * extFactor);
                attr.unblock = Math.ceil(attr.unblock * extFactor);
                attr.block = Math.ceil(attr.block * extFactor);
                attr.critdamage = Math.ceil(attr.critdamage * extFactor);
                attr.miss = Math.ceil(attr.miss * extFactor);
            }
        }

        var morale = attr.hasOwnProperty('morale') ? attr.morale : 200;
        var health = attr.health || 1;
        var initHealth = attr.initHealth || health;

        var soldierInit = gConfSoldierInit[soldierKind];
        var skill = +role.Skill;

        var posRole = {
            'id' : role.Id,                           // 英雄ID
            'xp' : 0,                                 // 经验
            'level' : level,                          // 英雄等级
            'soldierLevel' : role.SoldierLevel,       // 兵种等级
            'attack' : attr.attack,                   // 攻击
            'defence' : attr.defence,                 // 武防
            'mdefence' : attr.mdefence,               // 魔防
            'baseAttack' : attr.attack,               // 基础攻击
            'baseDefence' : attr.defence,             // 基础武防
            'baseMdefence' : attr.mdefence,           // 基础魔防
            'block' : attr.block,                     // 格挡
            'fortitude' : attr.fortitude,             // 刚毅
            'hit' : attr.hit,                         // 命中
            'unblock' : attr.unblock,                 // 破招
            'critDamage' : attr.critdamage,           // 暴击
            'miss' : attr.miss,                       // 闪避
            'health' : initHealth,                    // 血量
            'skill' : skill,                          // 主动技能ID
            'skillLevels' : {},                       // 技能等级对象,{id:level}
            'fightForce' : attr.fight_force,          // 战斗力
            'pos' : pos,                              // 英雄位置
            'initPos' : pos,                          // 英雄初始位置
            'soldierKind' : soldierKind ,             // 兵种
            'round' : 0,                              // 当前回合数
            'statusArr': [1, 0, health, 0, 200, 0],   // 战斗状态 
            'bufs'   : {},                            // 英雄战斗时的技能buf 
            'skills' : {},                            // 英雄初始化时的技能
            'initHit': soldierInit.Hit,               // 初始命中几率
            'initMiss': soldierInit.Miss,             // 初始闪避几率
            'initBlock' : soldierInit.Block,          // 初始格挡几率
            'initUnblock' : soldierInit.Unblock,      // 初始破招几率
            'initCritDamage' : soldierInit.Critdamage,// 初始暴击几率
            'initFortitude' : soldierInit.Fortitude,  // 初始刚毅
            'god': god,                               // 神将等级
            'wing':role.Wing || 0,                    // 羽翼等级
        }

        if (star) {
            var restrainAttrs = gConfRuntime.RoleStarRestrainAttrs[soldierKind][star];
            objectForEach(restrainAttrs, function(key, value) {
                posRole[key] = value;
            });
        }
        
        var skillLevels = posRole.skillLevels;
        skillLevels[skill] = role.SkillLevel; 
        if (eid) {
            var equalRoleConf = gConfRole[eid];

            if (equalRoleConf.SpecialSkill && role.SpecialSkill1) {
                skillLevels[equalRoleConf.SpecialSkill] = role.SpecialSkill1;
            }

            if (equalRoleConf.SpecialSkill2 && role.SpecialSkill2) {
                skillLevels[equalRoleConf.SpecialSkill2] = role.SpecialSkill2;
            }

            if (posRole.god >= 2) {
                var roleIndex = gSpecRoleIndex[eid];
                this['SpecRoleOf'+roleIndex] = rid;
            }
        }

        for (var skillId in skillLevels) {
            skillId = +skillId;
            var skillLevel = skillLevels[skillId];
            var skillKind = gGetSkillKind(soldierKind, skillId);
            var skillEffect = gConfSkillEffect[skillKind][skillId][skillLevel];

            posRole.skills[skillEffect['Effect']] = {
                'param' : skillEffect['Param'],
                'damage' : skillEffect['Damage'],
                'round' : skillEffect['Round'],
                'isSelf' : skillEffect['IsSelf'],
                'isActive' : (skillEffect['Type'] == 1 ? 1:0 ), //是否主动技能
            };   
        }

        this.roles[pos] = posRole;
        this.rolePoses[rid] = pos;
        this.team[pos] = rid;
        this.teamHealth += health;
        this.teamFightForce += posRole.fightForce;
        this.alive++;
        this.alivePosArr.push(pos);
    },

    _initPlayerPet: function(player) {
        var pet = player.user.pet; 
        if (!pet) {
            pet = {
                'level' : 1,
                'skills' : [],
                'skill_levels' : {'1':1},
            } 
        }

        this.pet = {
            'level' : pet.level, 
            'skills' : pet.skills.slice(),
            'skillLevels' : clone(pet.skill_levels),
        }
    },
    
    //从玩家属性映射NPC部队
    _mapNpcTeamMonsterFromPlayer: function(player, battle, factor) {
        var roleImages = player.getRoleImages();
        var monsterMap = {}; //{monsterId, rid}
        
        // 初始化阵型怪物列表
        var monsterNums = 0;
        var roleImageNums = Object.keys(roleImages).length;
        for (var pos = 0; pos < 9; ++pos) {
            if (monsterNums >= roleImageNums) {
                break;
            }

            var monsterId = battle['Pos'+pos];
            if (monsterId) {
                monsterMap[monsterId] = 0;
                monsterNums++;
            }
        }

        //玩家武将镜像的武将类型类型
        var roleImageKinds = {};
        objectForEachKey(roleImages, function(rid) {
            roleImageKinds[rid] = gConfRole[rid].Soldier;
        });
        
        //映射同类型武将
        objectForEachKey(monsterMap, function(monsterId) {
            var monsterConf = gConfMonster[monsterId];
            for (var rid in roleImageKinds) {
                if (roleImageKinds[rid] == monsterConf.Soldier) {
                    roleImageKinds[rid] = 0;
                    monsterMap[monsterId] = rid;
                    break;
                }
            }
        });
        
        //映射不同类型武将
        objectForEachKey(monsterMap, function(monsterId) {
            if (monsterMap[monsterId]) {
                return;
            }

            for (var rid in roleImageKinds) {
                if (roleImageKinds[rid]) {
                    roleImageKinds[rid] = 0;
                    monsterMap[monsterId] = rid;
                    break;
                }
            }
        });

        //根据映射结果读取镜像属性
        var monsterAttrs = {};
        objectForEachKey(monsterMap, function(monsterId) {
            var rid = monsterMap[monsterId];
            if (rid) {
                var attr = clone(roleImages[rid]);
                if (factor) {
                    gRoleBasicAttrNameArr.forEach(function(key) {
                        attr[key] = Math.floor((attr[key]||0) * factor);
                    });
                }
                monsterAttrs[monsterId] = attr;
            }
        });

        return monsterAttrs;
    },

    setBossHealthBeforeFight : function(health, initHealth) {

        health = parseInt(health);
        if (!initHealth) {
            initHealth = health;
        }

        this.teamHealth = 0;
        var roles = this.roles;
        for (var pos in roles) {
            var role = roles[pos];
            role.health = initHealth;
            role.statusArr[2] = health;
            this.teamHealth += health;
        }
    },

    addAttackBeforeFight : function(rate) {
        if (!rate) {
            return;
        }

        var roles = this.roles;
        for (pos in roles) {
            var role = roles[pos];
            role.baseAttack = Math.floor(role.baseAttack * (1 + rate/100));
            role.attack = role.baseAttack;
        }
    },

    setHealthBeforeFight: function(rate) {
        rate = Math.min(rate, 100);
        this.teamHealth = 0;
        var roles = this.roles;
        for (var pos in roles) {
            var role = roles[pos];
            var health = Math.max(1, Math.floor(role.health*rate/100));
            role.statusArr[2] = health;
            this.teamHealth += health;
        }
    },

    addDefenceValueBeforeFight: function(value) {
        if (!value) {
            return;
        }

        var roles = this.roles;
        for (pos in roles) {
            var role = roles[pos];
            role.defence += value;
            role.baseDefence += value;
        }
    },

    addMdefenceValueBeforeFight: function(value) {
        if (!value) {
            return;
        }

        var roles = this.roles;
        for (pos in roles) {
            var role = roles[pos];
            role.mdefence += value;
            role.baseMdefence += value;
        }
    },

    addDefenceBeforeFight: function(rate) {
        if (!rate) {
            return;
        }

        var roles = this.roles;
        for (pos in roles) {
            var role = roles[pos];
            role.defence = Math.floor(role.defence * (1 + rate/100));
            role.baseDefence = role.defence;
        }
    },

    addMdefenceBeforeFight: function(rate) {
        if (!rate) {
            return;
        }

        var roles = this.roles;
        for (pos in roles) {
            var role = roles[pos];
            role.mdefence = Math.floor(role.mdefence * (1 + rate/100));
            role.baseMdefence = role.mdefence;
        }
    },

    getTeamInfoBeforeFight : function(){
        var teamInfo = {};
        
        for( var pos in this.team){
            var rid = this.team[pos];

            if( !rid ){
                continue;
            }

            var role = this.roles[pos];
            teamInfo[pos] = {
                'id' : role.id,
                'level' : role.level,
                'soldier_level' : role.soldierLevel,
                'power' : role.statusArr[4],
                'initHealth' : role.health,
                'health' : role.statusArr[2],
                'skill': role.skill,
                'god':role.god,
                'wing':role.wing,
            }
        }
        
        return teamInfo;
    },

    initStatBeforeFight : function() {
        for (pos in this.roles) {
            var role = this.roles[pos];

            var addPowerDefault = this.getRoleHoroscopeValue(role, 'PowerDefault');
            if (addPowerDefault) {
                role.statusArr[4] += addPowerDefault;
            }

            role.stat = {
                'skillTimes' : 0,                            // 技能触发次数统计
            }
        }
    },

    getRemainInfoAfterFight : function () {
        var remainInfo = {};

        for (var pos in this.roles) {
            var role = this.roles[pos];
            if (role) {
                var roleStatus = role.statusArr;
                remainInfo[role.id] = {
                    health: roleStatus[2],
                    morale: roleStatus[4],
                }
            }
        }

        return remainInfo;
    },

    getTeamInitHealth: function() {
        var teamHealth = 0;
        objectForEach(this.roles, function(pos, role) {
            if (role) {
                teamHealth += (role.health || 1);
            }
        });
        return teamHealth;
    },
    
    getTeamRemainHealth: function() {
        var teamHealth = 0;
        objectForEach(this.roles, function(pos, role) {
            if (role) {
                teamHealth += (role.statusArr[2] || 0);
            }
        });
        return teamHealth;
    },
    
    //计算先手积分
    getInitiativeScore: function() {
		var score = 0;
		for (var rid in this.roles) {
			var role = this.roles[rid];
            if (role) {
				var fightForce = role.fightForce;
                var factor = this.getRoleHoroscopeValue(role, 'TemporaryFightForce');
				if (factor) {
					fightForce += Math.floor(fightForce*factor/100);
				}
				score += fightForce;
			}
        }
        return score;
    },

    fight : function(defender){
        this.initStatBeforeFight();
        defender.initStatBeforeFight();

        this.doSkillAddAttributes(defender);
        defender.doSkillAddAttributes(this);

        var battleReport = {
            success: 0,         
            rounds: {},         
            pet_rounds:{},
            atk_headpic : this.headpic,
            atk_name : this.name,
            atk_special_role_name : this.specialRoleName,
            atk_level : this.userLevel,
            atk_team_health: this.teamHealth,  
            atk_remain_health: 0,
            atk_team: this.getTeamInfoBeforeFight(),
            atk_pet:null,            
            def_headpic : defender.headpic,
            def_name : defender.name,
            def_special_role_name : defender.specialRoleName,
            def_level : defender.userLevel,
            def_team_health: defender.teamHealth,  
            def_remain_health :0,
            def_team: defender.getTeamInfoBeforeFight(),
            def_pet:null,
            over_rounds : 0,
            atk_remain_info : null,
            def_remain_info : null,
        };

        battleReport.atk_pet = {
            'level' : this.pet.level,
            'skills' : this.pet.skills,
            'skill_levels': this.pet.skill_levels,
        }

        battleReport.def_pet = {
            'level' : defender.pet.level,
            'skills' : defender.pet.skills,
            'skill_levels': defender.pet.skill_levels,
        }

        this.isAttacker = 1; 
        var isFirstMove = true;
        
        if ('user' == this.type) {
            if ('user' == defender.type) {
                isFirstMove = (this.getInitiativeScore() >= defender.getInitiativeScore()) ? true : false;
            } else {
                isFirstMove = true;
            }
        }

        var curRound = 1;
        var maxRound = 10;
        var firster,seconder;

        if( isFirstMove ) {
            firster = this;
            seconder = defender;
        }else{
            firster = defender;
            seconder = this;
        }

        for( var curRound = 1; curRound <= maxRound; curRound++) {
            var firsterPos  = 0;    // 先手方行动位置
            var seconderPos = 0;    // 后手方行动位置
            var matchPos = 0;
            var action = null;

            firster.prepareRoundStatus();
            seconder.prepareRoundStatus();
            
            battleReport.rounds[curRound] = [];
            
            // 神兽技能释放逻辑
            if( (firster.userLevel >= gConfGlobal.PetOpenLevel ||
                seconder.userLevel >= gConfGlobal.PetOpenLevel)
                && curRound <= 7 ) {


                var firsterPetSkills = firster.pet.skills;  
                var seconderPetSkills = seconder.pet.skills;
                
                var firsterPetSkillId = firsterPetSkills[curRound-1];
                var seconderPetSkillId = seconderPetSkills[curRound-1];
                if( firsterPetSkillId  || seconderPetSkillId ) {
                    battleReport.pet_rounds[curRound] = [];
                }

                if( (firster.userLevel >= gConfGlobal.PetOpenLevel) && firsterPetSkillId ) {
                    action = firster.getPetAction(seconder, firsterPetSkillId, curRound);  
                    battleReport.pet_rounds[curRound].push(action);
                }

                if( (seconder.userLevel >= gConfGlobal.PetOpenLevel) && seconderPetSkillId ) {
                    action = seconder.getPetAction(firster, seconderPetSkillId, curRound);  
                    battleReport.pet_rounds[curRound].push(action);
                }
            }


            // 战前处理逻辑
            firster.doPreAction(battleReport, curRound, seconder);
            seconder.doPreAction(battleReport, curRound, firster);


            // 正常战斗逻辑
            while( firsterPos < 9 || seconderPos < 9){

                if( firster.isAllDead()){
                    seconder.isWin = 1;
                    break;
                }

                firsterPos = firster.findAttackPos(firsterPos, curRound);

                if( firsterPos < 9){
                    matchPos = seconder.findDefendPos(firsterPos);    

                    if( matchPos < 0){
                        firster.isWin = 1;
                        break;
                    }

                    action = firster.getAction(curRound, firsterPos, seconder, matchPos);
                    battleReport.rounds[curRound].push(action);
                }

                if( seconder.isAllDead()){
                    firster.isWin = 1;
                    break;
                }

                seconderPos = seconder.findAttackPos(seconderPos, curRound);
                if( seconderPos < 9){
                    matchPos = firster.findDefendPos(seconderPos);    

                    if( matchPos < 0){
                        seconder.isWin = 1;
                        break;
                    }
                    
                    action = seconder.getAction(curRound, seconderPos, firster, matchPos);
                    battleReport.rounds[curRound].push(action);
                }
            }
            
            // 神兽技能buf的移除
            firster.removePetSkillBufs();
            seconder.removePetSkillBufs(); 

            if( firster.isAllDead() || seconder.isAllDead() ) {
                break;
            }

        }

        battleReport.atk_remain_health = this.teamHealth;
        battleReport.def_remain_health = defender.teamHealth;

        if( curRound > maxRound ){
            defender.isWin = 1;
            battleReport.success = 0;
            battleReport.over_rounds = 1;
        }else{

            if( this.isWin){
                battleReport.success = 1;
            }else {
                battleReport.success = 0;
            } 
        }

        battleReport.atk_remain_info = this.getRemainInfoAfterFight();
        battleReport.def_remain_info = defender.getRemainInfoAfterFight();

        return battleReport;
    },

    doPreAction: function(report, curRound, defender) {
        for (var key in this.escapes) {
            var pos = +key;
            var health = this.escapes[pos];

            var role = this.roles[pos];
            if (!role || role.statusArr[0] != roleStatusMap.DEAD) {
                continue;
            }


            role.round = curRound - 1;
            role.bufs = {};
            role.statusArr = [1, 0, health, 0, 200, 0];
			role.escaped = true;

            this.teamHealth += health;
            this.alive++;
            this.alivePosArr.push(pos);

            var action = {
                'atk' : this.isAttacker ? 0 : 1,
                'atk_pos' : pos,
                'def_pos' : [],
                'atk_status' : { },
                'def_status' : { },
                'skill' : 'Escape',
                'isself': 0,
                'type': ActionType.Pre,
            };
            action.atk_status[role.pos] = [1, 0, health, health, 200, 0]

            report.rounds[curRound].push(action);
        }
        this.escapes = {};
    },

    getAction: function(curRound, atkPos, defender, defPos){
        var action = {
            'atk' : 0 , 
            'atk_pos' : atkPos,
            'def_pos' : [],
            'atk_status' : { },
            'def_status' : { },
            'skill' : 0,
            'isself': 0,
        };
        action.atk = this.isAttacker ? (0) : (1);

        var isSkillJudge = 1;
        var isCalculateDamage = 1;
        var addPowerDamageFactor = 0;

        var defPosArr = [];
        defPosArr.push(defPos);
        var atkRole = this.roles[atkPos];
        var atkSkill = atkRole['skill'];

        var atkAlive = this.alive; 
        atkRole.statusArr[1] = 0;
        atkRole.statusArr[3] = 0;
        atkRole.statusArr[5] = 0;
        atkRole.status = RoleStatus.Action;

        for (var pos in defender.roles) {
            var role = defender.roles[pos];
            if (role) {
                role.statusArr[1] = 0;
                role.statusArr[3] = 0;
                role.statusArr[5] = 0;
            }
        }

        //攻击方状态的判定
        if( roleStatusMap.CONFUSE == atkRole.statusArr[0] && atkAlive > 1){
            action.isself = 1;
            isSkillJudge = 0;
            atkRole.statusArr[0] = roleStatusMap.NORMAL;
            defPosArr.remove(defPos);
            defPosArr.push(this.randOneFriendPos(atkPos));

        }else if( roleStatusMap.CONFUSE == atkRole.statusArr[0] && 1 == atkAlive){
            isSkillJudge = 0;
            atkRole.statusArr[0] = roleStatusMap.NORMAL;

        }else if( roleStatusMap.SLEEP == atkRole.statusArr[0] ){
            isSkillJudge = 0;
            isCalculateDamage = 0;
            defPosArr.remove(defPos);
            action.atk_status[atkPos] = [];
            atkRole.statusArr[0] = roleStatusMap.NORMAL;
            action.atk_status[atkPos] = atkRole.statusArr.slice();
        }
        
        var skills = atkRole.skills;
        if( isSkillJudge ){
            var atkSoldierKind = atkRole.soldierKind;
            // 士气大于等于400
            if( atkRole.statusArr[4] >= 400){
                if( gSoldierKindMap.SPEAR == atkSoldierKind ){
                    if( 'atkrow' in skills){
                        defender.getAtkRowPos(defPosArr);        
                    }

                }else if( gSoldierKindMap.RIDER == atkSoldierKind){
                    if( 'atkcol' in skills){
                        defender.getAtkColPos(defPosArr);
                    }else if( 'atklast' in skills){
                        defender.getAtkLastPos(defPosArr); 
                    }
                    
                }else if( gSoldierKindMap.ADVISER == atkSoldierKind){
                    if( 'atkall' in skills){
                        defender.getAtkAllPos(defPosArr); 
                    }
                }
                
                addPowerDamageFactor = (atkRole.statusArr[4] - 400)/800;
                //星座效果-盛气临人, 提升士气对技能伤害的影响
                var hsPowerEffect = this.getRoleHoroscopeValue(atkRole, 'PowerEffect')
                if (hsPowerEffect) {
                    addPowerDamageFactor *= (1 + hsPowerEffect/100);
                }

                //释放技能后士气归0
                atkRole.statusArr[4] = 0;
                atkRole.stat.skillTimes += 1;
                action.skill = atkRole.skill;
            }
        }

        if( isSkillJudge && skills.hasOwnProperty('atkback')){
            action.def_pos.push(defPos);
        }else{ 
            action.def_pos = defPosArr;
        }
        
        for( var i = 0, len = skillEffectBufs.length; i < len; i++){
            var skillEffect = skillEffectBufs[i]; 
            if( atkRole.bufs.hasOwnProperty(skillEffect) 
                &&atkRole.bufs[skillEffect].round > 0){
                atkRole.bufs[skillEffect].round -= 1; 
            }
        }
        
        if( isCalculateDamage ){
            for( var i = 0, len = defPosArr.length; i < len; i++){
                if( 1 == action.isself && 0 == isSkillJudge){
                    this.calculateDamage(curRound, this, atkRole, this.roles[defPosArr[i]], action,addPowerDamageFactor);
                    break;
                }

                var isAtkRoleDead = this.calculateDamage(curRound, defender, atkRole, defender.roles[defPosArr[i]], action,addPowerDamageFactor);
                if( isAtkRoleDead ){
                    for( var j = i+1; j < len; j++) {
                        defPosArr.pop(); 
                    }
                    break;
                }
            } 

            if (!action.isself) {
                this.doActionFinish(action, defender, atkRole);

                // 邪赵云-绝世无双, 横扫千军附加%n的溅射伤害
                if ((this.SpecRoleOfZhaoYun == atkRole.id) && (3 == action.skill)) {
                    var splashDamage = this.getRoleSkillDamage(atkRole, specRoleMap.ZhaoYun.godSkill);
                    this.doSkillActionSplash(action, defender, atkRole, defPosArr, splashDamage);
                }
                //吕布-傲视群雄，狂野践踏附加%n的溅射伤害
                else if ((this.SpecRoleOfLvBu == atkRole.id) && (3 == action.skill)) {
                    var splashDamage = this.getRoleSkillDamage(atkRole, specRoleMap.LvBu.lordSkill);
                    this.doSkillActionSplash(action, defender, atkRole, defPosArr, splashDamage);
                } 

                //邪关羽-义薄云天，使用技能后下一回攻击力增加%n
                if ((this.SpecRoleOfGuanYu == atkRole.id) && action.skill) {
                    var improveatkRate = this.getRoleSkillDamage(atkRole, specRoleMap.GuanYu.lordSkill);
                    if (improveatkRate > 0) {
                        this.doSkillActionAddBuf(action, atkRole, 'improveatk', improveatkRate, 1);
                    }
                }

                //童渊-魔龙嗜血, 八绝神龙附带%n的吸血效果
                if ((this.SpecRoleOfTongYuan == atkRole.id) && (5 == action.skill)) {
                    var suckRate = this.getRoleSkillParam(atkRole, specRoleMap.TongYuan.lordSkill);
                    if (suckRate > 0) {
                        this.doSkillActionSuck(action, defender, atkRole, suckRate);
                    }
                }

                //刘乐乐-真龙觉醒, 逆转锋芒可以攻击一条直线上的敌人，后排目标所受伤害逐渐递减为前一个的z%
                if ((this.SpecRoleOfLiuLeLe == atkRole.id) && (5 == action.skill)) {
                    var decreaseRate = this.getRoleSkillDamage(atkRole, specRoleMap.LiuLeLe.lordSkill);
                    if (decreaseRate > 0) {
                        this.doSkillActionDecreaseCol(action, defender, decreaseRate);
                    }
                }
            }
        }

        if( atkRole.bufs.hasOwnProperty('atktransdef') &&
            0 == atkRole.bufs['atktransdef']['round']){
            if( atkRole.bufs.hasOwnProperty('improveatk') 
                && atkRole.bufs['improveatk']['round'] > 0 ){
                if( atkRole.attack < atkRole.baseAttack){
                    atkRole.attack += atkRole.baseAttack;
                    atkRole.defence = atkRole.baseDefence;
                }
            }else{
                atkRole.attack = atkRole.baseAttack; 
                atkRole.defence = atkRole.baseDefence;
            }        
        }

        if( atkRole.bufs.hasOwnProperty('improveatk') &&
            0 == atkRole.bufs['improveatk']['round']){
            if( atkRole.bufs.hasOwnProperty('atktransdef')&&
                atkRole.bufs['atktransdef']['round'] > 0){
                if( atkRole.attack < atkRole.baseAttack){
                    atkRole.attack = 0;
                    atkRole.defence = atkRole.baseAttack + atkRole.baseDefence;
                }
            
            }else{
                atkRole.attack = atkRole.baseAttack;
                atkRole.defence = atkRole.baseDefence;
            }
        }

        for( var i = 0 ,len = skillEffectBufs.length; i < len; i++){
            var skillEffect = skillEffectBufs[i]; 
            if( atkRole.bufs.hasOwnProperty(skillEffect) 
                && 0 == atkRole.bufs[skillEffect].round){
                this.removeOneFromBufs(atkRole, skillEffect);
            }
        }

        return action;
    },

    calculateDamage : function(curRound, defender, atkRole, defRole, action, addPowerDamageFactor){
        // 攻击方和防守方受到的伤害
        var atkDamage = 0;
        var defDamage = 0;

        var atkPosArr = [];
        atkPosArr.push(atkRole.pos);
        var defPos = defRole.pos;

        var atkSoldierKind = atkRole.soldierKind;
        var defSoldierKind = defRole.soldierKind;
        var atkIsMagic = gIsMagicSoldierKind(atkSoldierKind);

        var atkStatusArr = atkRole.statusArr;
        var defStatusArr = defRole.statusArr;

        var atkLevel = atkRole.level;
        var defLevel = defRole.level;
        
        defStatusArr[1] = 0;
        defStatusArr[3] = 0;
        defStatusArr[5] = 0;

        var defRespStatus = 0;
        var basicDamageFactor = 1.0;
        var correctionValue = 7000;
        var convertFactor = 0.7;
        var skill  = action.skill;
        var effect= ''; // 技能效果

        // 红颜的加血和提升全体攻击的技能不能被闪避
        // 红颜释放以上两种技能时，格挡和暴击几率均为0
        var isBeautySelfSkill = false;
        if( gSoldierKindMap.BEAUTY == atkSoldierKind &&
            (1 == skill || 3 == skill) ) {
            isBeautySelfSkill = true;
        }
        
        //闪避
        var missDiff = defRole.miss - 0.9 * atkRole.hit;
        var missDiffAbs = Math.abs(missDiff);
        var missChance = Math.floor(100*(0.25*missDiffAbs)/(missDiffAbs + 4000));
        if( missDiff < 0 ){
            missChance = -missChance;          
        }

        var missRate = defRole.initMiss - atkRole.initHit + missChance ; 

        if (defender.SpecRoleOfGuanYu) {
            //关羽-忠义无双, 上阵后提升全员n%闪避率
            missRate += defender.getRoleIdSkillParam(defender.SpecRoleOfGuanYu, specRoleMap.GuanYu.godSkill);
        }

        if (1 == curRound) {
            //星座效果
            missRate += defender.getRoleHoroscopeValue(defRole, 'EarliestMiss');
            missRate -= this.getRoleHoroscopeValue(atkRole, 'EarliestHit');
        }

        if( missRate <= 0 || isBeautySelfSkill ){
            missRate = 0;
        }

        if (missRate > 0 && common.randRange(1,100) <= missRate) {
            defRespStatus = defRespMap.MISS;
            defStatusArr[5] = defRespStatus;
            if (gSoldierKindMap.RIDER == defSoldierKind) {
                defStatusArr[4] += 60; 
            }
        } else {
            if (!isBeautySelfSkill) {
                //格挡
                var blockRate = 0;
                if(!atkIsMagic) {
                    var blockDiff = defRole.block - 1.2 * atkRole.unblock;
                    var blockDiffAbs = Math.abs(blockDiff);
                    var blockChance = Math.floor(100*(0.5*blockDiffAbs)/(blockDiffAbs + 5000));

                    if( blockDiff < 0 ){
                        blockChance = -blockChance;          
                    }
                    
                    blockRate = defRole.initBlock - atkRole.initUnblock + blockChance ; 

                    if (1 == curRound) {
                        //星座效果
                        blockRate += defender.getRoleHoroscopeValue(defRole, 'EarliestBlock');
                        blockRate -= this.getRoleHoroscopeValue(atkRole, 'EarliestUnblock');
                    }

                    if( blockRate <= 0){
                        blockRate = 0;
                    }
                       
                    if (blockRate > 0 && common.randRange(1, 100) <= blockRate){
                        basicDamageFactor = 0.5;
                        defRespStatus = defRespMap.BLOCK;
                        defStatusArr[5] = defRespStatus;
                        if( gSoldierKindMap.SWORD == defSoldierKind){
                            defStatusArr[4] += 40; 
                        }
                    }
                } 
                
                //暴击
                var critDamageRate = 0;
                if(defRespMap.BLOCK != defRespStatus) {
                    var critDamageDiff = atkRole.critDamage - 0.6 * defRole.fortitude;
                    var critDamageDiffAbs = Math.abs(critDamageDiff);
                    var critDamageChance = Math.floor(100*(0.4*critDamageDiffAbs)/(critDamageDiffAbs + 3000));

                    if( critDamageDiff < 0 ){
                        critDamageChance = -critDamageChance;          
                    }
                    
                    critDamageRate = defRole.initCritDamage - atkRole.initFortitude + critDamageChance ; 
                    
                    if (this.SpecRoleOfZhaoYun) {
                        critDamageRate += this.getRoleIdSkillParam(this.SpecRoleOfZhaoYun, specRoleMap.ZhaoYun.lordSkill);
                    }

                    if (this.SpecRoleOfXiangYu == atkRole.id) {
                        critDamageRate += this.getRoleSkillParam(atkRole, specRoleMap.XiangYu.godSkill);
                    }

                    if (1 == curRound) {
                        //星座效果
                        critDamageRate += this.getRoleHoroscopeValue(atkRole, 'EarliestCritdamage');
                        critDamageRate -= defender.getRoleHoroscopeValue(defRole, 'EarliestFortitude');
                    }

                    if( critDamageRate <= 0){
                        critDamageRate = 0;
                    }

                    if( critDamageRate > 0 && common.randRange(1, 100) <= critDamageRate){
                        basicDamageFactor = 1.5;
                        defRespStatus = defRespMap.CRIT;
                        defStatusArr[5] = defRespStatus;
                        if( !skill && gSoldierKindMap.SPEAR == atkSoldierKind){
                            atkStatusArr[4] += 100; 
                        }
                    }
                }
                
                var attackSum = atkRole.attack;
                var attackAddRate = 0;
                var defenceSum = 0;
                var defenceAddRate = 0;
                //读取英雄原有的攻击和防御 
                if (atkIsMagic) {
                    defenceSum = defRole.mdefence;
                } else {
                    defenceSum = defRole.defence;
                }
                
                if (this.isRoleHealthFull(atkRole)) {
                    //星座效果-奇袭, 士兵满时攻击(武力/谋略)增加
                    attackAddRate += this.getRoleHoroscopeValue(atkRole, 'MaxHpAttack');
                } else if (this.isRoleNearDeath(atkRole)) {
                    //星座效果-背水, 濒死时攻击(武力/谋略)增加
                    attackAddRate += this.getRoleHoroscopeValue(atkRole, 'MoribundAttack');
                }

                if (defender.isRoleNearDeath(defRole)) {
                    //星座效果-坚守/护心, 濒死时武防/谋防增加
                    defenceAddRate += defender.getRoleHoroscopeValue(defRole, 
                        atkIsMagic ? 'MoribundMagicDefence' : 'MoribundDefence');
                }

                if (1 == curRound) {
                    //星座效果
                    attackAddRate += this.getRoleHoroscopeValue(atkRole, 'EarliestAttack');
                    defenceAddRate += defender.getRoleHoroscopeValue(defRole, 
                        atkIsMagic ? 'EarliestMDefence' : 'EarliestDefence');
                }


                // 邪贾诩
                if((this.SpecRoleOfJiaXu == atkRole.id) && skill &&(this.getRoleActiveSkillEffect(atkRole) == 'atkall') ) {
                    defenceAddRate -= this.getRoleSkillParam(atkRole, specRoleMap.JiaXu.godSkill);
                }

                // 邪华佗 
                if( this.SpecRoleOfHuaTuo ) {
                    var addBaseAtkParam = this.getRoleIdSkillParam(this.SpecRoleOfHuaTuo, specRoleMap.HuaTuo.godSkill);
                    var addAtk = Math.floor(atkRole.baseAttack * addBaseAtkParam / 100);
                    
                    if( this.alivePosArr.indexOf(this.rolePoses[this.SpecRoleOfHuaTuo]) >= 0 ) {
                        attackSum += (addAtk * atkRole.round);
                    }else {
                        attackSum += (addAtk * this.roles[this.rolePoses[this.SpecRoleOfHuaTuo]].round);
                    }
                }

                //刘乐乐-逆转乾坤, 逆转锋芒技能施放后保留x%的武力
                if (this.SpecRoleOfLiuLeLe == atkRole.id) {
                    if (atkRole.bufs.hasOwnProperty('atktransdef') && atkRole.bufs['atktransdef']['round'] >= 0) {
                        attackSum += Math.floor(atkRole.baseAttack * this.getRoleSkillParam(atkRole, specRoleMap.LiuLeLe.godSkill)/100);
                    }
                }
                
                //普通伤害计算
                attackSum = Math.floor(attackSum * (1 + attackAddRate/100));
                defenceSum = Math.floor(defenceSum * (1 + defenceAddRate/100) *0.7);
                defDamage = 0 - (attackSum + common.randRange(atkLevel, 20*atkLevel))
                    *(1 - (defenceSum  / ( defenceSum + 50*atkLevel + 100)));
            }

            //技能
            if( !skill ){
                atkStatusArr[4] += 100;
                defStatusArr[4] += 100;
            }else{
                effect = this.getRoleActiveSkillEffect(atkRole);

                var skillDamageFactor = atkRole.skills[effect]['damage']/100;
                switch( effect ){
                    case 'rehurt':
                        this.addOneToBufs(atkRole, 'rehurt', atkRole.skills['rehurt']);    
                        action.isself = 0;
                        break;
                    case 'strongatk':
                        skillDamageFactor = skillDamageFactor*(1 + (this.total - this.alive)*0.1);
                        break;
                    case 'atktransdef':
                        if (!atkRole.bufs.hasOwnProperty('atktransdef')) {
                            atkRole.attack -= atkRole.baseAttack; 
                            atkRole.defence = atkRole.baseAttack + atkRole.baseDefence;
                        }

                        if (atkRole.bufs.hasOwnProperty('improveatk') &&
                            atkRole.bufs['improveatk']['round'] > 0){
                            if (atkRole.attack > atkRole.baseAttack){
                                atkRole.attack -= atkRole.baseAttack;
                            } 
                        }

                        this.addOneToBufs(atkRole, 'atktransdef', atkRole.skills['atktransdef']);    
                        break;
                    case 'atkback':
                        defStatusArr[1] = defender.getAtkBackPos(action.def_pos);     
                        break;
                    case 'sleep':
                        {
                            if( defRole.bufs.hasOwnProperty('confuse')){
                                this.removeOneFromBufs(defRole, 'confuse');  
                            }
                            defRole.statusArr[0] = roleStatusMap.SLEEP;
                            this.addOneToBufs(defRole, 'sleep', atkRole.skills['sleep']);    
                        }
                        break;
                    case 'confuse':
                        if( gSoldierKindMap.BEAUTY != defSoldierKind ){
                            var confuseRate = Math.floor(atkRole.skills['confuse']['param'] + attackSum*50/(attackSum + 100));
                            if( confuseRate > 0 && common.randRange(1, 100) <= confuseRate*2){
                                if( defRole.bufs.hasOwnProperty('sleep')){
                                    this.removeOneFromBufs(defRole, 'sleep');  
                                }
                                defRole.statusArr[0] = roleStatusMap.CONFUSE;
                                this.addOneToBufs(defRole, 'confuse', atkRole.skills['confuse']);    
                            }
                        }
                        break;
                    case 'improveatk':
                        action.isself = 1;
                        action.def_pos.remove(defRole.pos);
                        var addAttack = Math.floor(atkRole.baseAttack*atkRole.skills['improveatk']['param']/100);
                        for( var i = 0, len = this.alivePosArr.length; i < len; i++){
                            var pos = this.alivePosArr[i];    
                            var role = this.roles[pos];
                            var roleStatusArr = role.statusArr;
                            if( pos !=  atkRole.pos){
                                atkPosArr.push(pos); 
                            }

                            roleStatusArr[1] = 0;
                            roleStatusArr[3] = 0;
                            roleStatusArr[5] = 0;

                            if (role.bufs.hasOwnProperty('atktransdef') 
                                && role.bufs['atktransdef']['round'] > 0) {
                                role.attack = addAttack; 
                            
                            }else{
                                role.attack = role.baseAttack + addAttack;
                            }

                            this.addOneToBufs(role, 'improveatk', atkRole.skills['improveatk']);    
                        }
                        break;

                    case 'health':
                        action.isself = 1;
                        action.def_pos.remove(defRole.pos);
                        var addHealth = Math.floor(atkRole.baseAttack*(atkRole.skills['health']['param'])/100);
                        for( var i= 0, len = this.alivePosArr.length; i < len; i++) {
                            var pos = this.alivePosArr[i];
                            var role = this.roles[pos];
                            var roleStatusArr = role.statusArr;
                            if( pos !=  atkRole.pos) {
                                atkPosArr.push(pos); 
                            }

                            roleStatusArr[0] = roleStatusMap.NORMAL;
                            roleStatusArr[1] = 0;
                            roleStatusArr[3] = 0;
                            roleStatusArr[5] = 0;
                            var realAddHealth = Math.min(Math.abs(role.health - roleStatusArr[2]), addHealth);
                            this.addRoleHealthInFight(role, realAddHealth);

                            var buffName = 'sleep';
                            var roleBuf = role.bufs[buffName];
                            if (roleBuf) {
                                if (!roleBuf.layer || roleBuf.layer < BufLayerLevel.STICK) {
                                    this.removeOneFromBufs(role, buffName);    
                                } else {
                                    roleStatusArr[0] = roleStatusMap.SLEEP;
                                }
                            }
                            
                            buffName = 'confuse';
                            roleBuf = role.bufs[buffName];
                            if (roleBuf) {
                                if (!roleBuf.layer || roleBuf.layer < BufLayerLevel.STICK) {
                                    this.removeOneFromBufs(role, buffName);    
                                } else {
                                    roleStatusArr[0] = roleStatusMap.CONFUSE;
                                }
                            }
                        }
                        break;
                    default : break;
                }
                
                var addSkillDamageFactor = 0;
                if ('atkback' == effect) {
                    if (this.SpecRoleOfTongYuan == atkRole.id) {
                        //童渊-狂龙绝杀, 提升八绝神龙技能%n的伤害
                        addSkillDamageFactor += this.getRoleSkillDamage(atkRole, specRoleMap.TongYuan.godSkill);
                    }
                } else if ('atkall' == effect) {
                    if (this.SpecRoleOfZhuGeliang == atkRole.id) {
                        //诸葛亮-呼风唤雨, 提升半步定江山技能%n的伤害
                        addSkillDamageFactor += this.getRoleSkillDamage(atkRole, specRoleMap.ZhuGeliang.godSkill);
                    } else if (this.SpecRoleOfZuoCi == atkRole.id) {
                        //左慈-五雷轰顶, 提升半步定江山技能%n的伤害
                        addSkillDamageFactor += this.getRoleSkillDamage(atkRole, specRoleMap.ZuoCi.godSkill);

                        //左慈-九星连珠, 半步定江山附带%n的眩晕效果
                        var defSleepRate = this.getRoleSkillParam(atkRole, specRoleMap.ZuoCi.lordSkill);
                        if (defSleepRate > 0) {
                            defender.doSkillActionAddBuf(action, defRole, 'sleep', defSleepRate, 1);
                        }
                    } else if (this.SpecRoleOfJiaXu == atkRole.id) {
                        //贾诩-奇谋百出, 提升半步定江山技能%n的伤害
                        addSkillDamageFactor += this.getRoleSkillDamage(atkRole, specRoleMap.JiaXu.godSkill);

                        //贾诩-算无遗策, 半步定江山附带%n的沉睡效果
                        var defSleepRate = this.getRoleSkillParam(atkRole, specRoleMap.JiaXu.lordSkill);
                        if (defSleepRate > 0) {
                            defender.doSkillActionAddBuf(action, defRole, 'sleep', defSleepRate, 1);
                        }
                    }

                    if (defender.SpecRoleOfZhuGeliang) {
                        //诸葛亮-洞测天机, 诸葛亮在场时，敌方半步定江山的伤害降低5%
                        addSkillDamageFactor -= defender.getRoleIdSkillParam(defender.SpecRoleOfZhuGeliang, specRoleMap.ZhuGeliang.lordSkill);
                    }
                } else if ('strongatk' == effect) {
                    if (this.SpecRoleOfDongZuo == atkRole.id) {
                        //董卓-战神附体, 技能天怒碎龙斩的伤害增加%n
                        addSkillDamageFactor += this.getRoleIdSkillDamage(this.SpecRoleOfDongZuo, specRoleMap.DongZuo.lordSkill);
                    }
                } else if ('atkrow' == effect) {
                    if (this.SpecRoleOfXiangYu == atkRole.id) {
                        if (defRespMap.CRIT == defStatusArr[5]) {
                            atkStatusArr[4] = this.getRoleSkillDamage(atkRole, specRoleMap.XiangYu.godSkill);
                        }
                       
                        addSkillDamageFactor += this.getRoleSkillDamage(atkRole, specRoleMap.XiangYu.lordSkill)*(atkRole.stat.skillTimes - 1);
                    }
                } else if ('atkcol' == effect) {
                    if (this.SpecRoleOfMaChao && (specRoleMap.MaChao.id == atkRole.id)) {
                        //马超-踏破山河, 马超的狂野践踏技能伤害提升x%，并有y%几率降低对手100点士气
                        addSkillDamageFactor += this.getRoleIdSkillDamage(atkRole.id, specRoleMap.MaChao.godSkill);
                        var reduceRate = this.getRoleIdSkillParam(atkRole.id, specRoleMap.MaChao.godSkill);
                        this.doSkillActionReduceMorale(action, defender, defRole, reduceRate, 100);
                    }
                } else if ('atktransdef' == effect) {
                    if (this.SpecRoleOfLiuLeLe == atkRole.id) {
                        //刘乐乐-逆转乾坤, 逆转锋芒如果目标本回合未出手则将其击晕
                        if (!defRole.status) {
                            this.doSkillActionAddBuf(action, defRole, 'sleep', 100, 1);
                        }
                    }
                }

                if (gSoldierKindMap.RIDER == atkSoldierKind) {
                    if (this.SpecRoleOfLvBu) {
                        //吕布-天下无敌, 上阵后所有骑兵武将技能增加%n伤害
                        addSkillDamageFactor += this.getRoleIdSkillDamage(this.SpecRoleOfLvBu, specRoleMap.LvBu.godSkill);
                    }
                } else if (gSoldierKindMap.SWORD == atkSoldierKind) {
                    if (this.SpecRoleOfDianWei) {
                        //典韦-猛虎下山, 上阵后所有刀兵武将技能伤害增加%n
                        addSkillDamageFactor += this.getRoleIdSkillDamage(this.SpecRoleOfDianWei, specRoleMap.DianWei.lordSkill);
                    }
                }

                if (this.SpecRoleOfMaChao && !gIsMagicSoldierKind(atkSoldierKind)) {
                    //马超-天降神威, 上阵后所有刀兵、枪兵、骑兵武将技能伤害增加x%
                    var machaoLordDamage = this.getRoleIdSkillDamage(specRoleMap.MaChao.id, specRoleMap.MaChao.lordSkill);
                    if (machaoLordDamage) {
                        var defCount = Math.max(1, action.def_pos.length);
                        addSkillDamageFactor += (machaoLordDamage/defCount);
                    }
                }

                skillDamageFactor *= (1 + addSkillDamageFactor/100);
                defDamage = defDamage*skillDamageFactor*(1 + addPowerDamageFactor);
            }
        }

        if (defRespMap.MISS == defRespStatus) {
            //星座效果-迂回之术, 闪避后额外增加士气
            defStatusArr[4] += defender.getRoleHoroscopeValue(defRole, 'PowerUpMiss');

            if (!skill) {
                //星座效果-打草惊蛇, 普通攻击未命中额外增加士气
                atkStatusArr[4] += this.getRoleHoroscopeValue(atkRole, 'MissedPowerUp');
            }
        } else {
            if (!isBeautySelfSkill) {
                if (!skill) {
                    //星座效果-步步为营, 普通攻击命中额外增加士气
                    atkStatusArr[4] += this.getRoleHoroscopeValue(atkRole, 'AttackPowerUp');
                    
                    //星座效果-临危不乱, 被普通攻击命中后额外增加士气
                    defStatusArr[4] += defender.getRoleHoroscopeValue(defRole, 'PowerUpHit');
                }

                if (defRespMap.BLOCK == defRespStatus) {
                    //星座效果-以守为攻, 格挡后额外增加士气
                    defStatusArr[4] += defender.getRoleHoroscopeValue(defRole, 'PowerUpBlock');
                }
            }
        }
        
        if( !isBeautySelfSkill ) {
            var extDamageFactor = 0;
            
            //技能BUFF加成
            if( atkRole.skills.hasOwnProperty('improvedamage')){
                extDamageFactor += atkRole.skills['improvedamage']['param'];
            }

            //神兽增加伤害
            if( atkRole.bufs.hasOwnProperty('improvehurt') ) {
                var petSkillLevel = this.pet.skillLevels[101];
                extDamageFactor = gConfPetSkillEffect[101][petSkillLevel].Param;
            }

            //董卓-不灭金甲, 上阵后增加全员%n的免伤效果
            if (defender.SpecRoleOfDongZuo) {
                extDamageFactor -= defender.getRoleIdSkillDamage(defender.SpecRoleOfDongZuo, specRoleMap.DongZuo.godSkill);
            }

            //洛神-出水芙蓉, 洛神受到的伤害降低%n
            if (defender.SpecRoleOfLuoShen == defRole.id) {
                extDamageFactor -=  defender.getRoleSkillParam(defRole, specRoleMap.LuoShen.lordSkill);
            }

            // 兵种克制
            var restrainRate = atkRole['Restrain'+defRole.soldierKind];
            if (restrainRate) {
                extDamageFactor += restrainRate;
            }
            
            //星座效果-趁火打劫, 对眩晕、沉睡、魅惑中的对手额外造成一定比例伤害
            var hsStunDamage = this.getRoleHoroscopeValue(atkRole, 'StunDamage');
			if (hsStunDamage && defender.isRoleExistBufs(defRole, 'sleep', 'confuse')) {
				extDamageFactor += hsStunDamage;
			}
            
            // 计算最终伤害
            defDamage *= (Math.max(0.01, 1 + extDamageFactor/100) * basicDamageFactor); 


            //邪貂蝉-闭月羞花, 每受到一次超过自身血量10%的伤害，谋略提升%n
            if ((defender.SpecRoleOfDiaoChan == defRole.id) &&
                (defDamage/defRole.health < -0.1)) {
                var attackRate = defender.getRoleSkillParam(defRole, specRoleMap.DiaoChan.lordSkill);
                var attackValue = Math.floor(defRole.baseAttack*attackRate/100);
                defRole.baseAttack += attackValue;
                defRole.attack += attackValue;
            }
            
            // 处理反弹
            if (roleStatusMap.DEAD != defRole.statusArr[0] && defRole.bufs.hasOwnProperty('rehurt')) {
                var rehurtFactor = defRole.bufs['rehurt']['param']/100;
                atkDamage = -Math.min((-1)*rehurtFactor*defDamage, defRole.health*0.8);
                atkStatusArr[5] = defRespMap.REBOUND;
            }

            defender.addRoleHealthInFight(defRole, Math.floor(defDamage));
            this.addRoleHealthInFight(atkRole, Math.floor(atkDamage));
        }
        
        for( var i = 0 , len = atkPosArr.length; i < len; i++){
            var pos = atkPosArr[i];
            action.atk_status[pos] = [];
            action.atk_status[pos] = this.roles[pos].statusArr.slice();
        }

        if( action.def_pos.length > 0 ){
            action.def_status[defPos] = [];
            action.def_status[defPos] = defRole.statusArr.slice();
        }

        return  (roleStatusMap.DEAD == atkStatusArr[0]) ;
    },

    //战斗中给武将增加/减少血量
    addRoleHealthInFight: function(role, value) {
        if (!value) {
            return;
        }

        var statusArr = role.statusArr;
        if (roleStatusMap.DEAD == statusArr[0]) {
            return;
        }

        if (value < 0 && this.damageFactor) {
            value = Math.ceil(this.damageFactor*value);
        }

        var oldHealth = statusArr[2];
        var addHealth = value;

        statusArr[2] += value;
        if (value > 0) {
            if (statusArr[2] > role.health) {
                statusArr[2] = role.health;
                addHealth = role.health - oldHealth;
            }
        } else {
            if (statusArr[2] <= 0) {
                statusArr[0] = roleStatusMap.DEAD;
                statusArr[2] = 0;
                statusArr[4] = 0;
                this.alive -= 1;
                this.alivePosArr.remove(role.pos);
                addHealth = -oldHealth;
                
                if (!role.escaped) {
                    var hsEscape = this.getRoleHoroscopeValue(role, 'Escape');
                    if (hsEscape) {
                        var health = hsEscape;
                        var hsEscapeUp = this.getRoleHoroscopeValue(role, 'EscapeUp');
                        if (hsEscapeUp) {
                            health = Math.max(health, Math.ceil(role.health*hsEscapeUp/100));
                        }
                        this.escapes[role.pos] = health;
                    }
                }
            }
        }

        //statusArr[3] += addHealth;
        statusArr[3] += value;
        this.teamHealth += addHealth;
    },
    
    //武将是否满血 
    isRoleHealthFull: function(role) {
        return role.statusArr[2] >= role.health;
    },

    //武将是否濒临死亡 
    isRoleNearDeath: function(role) {
        return role.statusArr[2] <= Math.floor(role.health*0.1);
    },
    
    //准备回合数据
    prepareRoundStatus: function() {
        //重置各武将状态
        objectForEach(this.roles, function(pos, role) {
            if (role) {
                delete role.status;
            }
        });
    },
    
    getAtkRowPos: function(defPosArr){
        var row  = Math.floor(defPosArr[0]/3);
        var posArr = rowSequence[row];
        for( var j = 0, len = posArr.length; j < len; j++){
            pos = posArr[j]; 

            if( this.alivePosArr.indexOf(pos) < 0){
                continue;
            }

            if( defPosArr[0] == pos ){
                continue;
            }

            defPosArr.push(pos);
        }
         
    },

    getAtkBackPos: function(defPosArr){
        var column = defPosArr[0] % 3;
        var posArr = colSequence[column];
        var oldPos = defPosArr[0];

        for( var i = posArr.length -1;  i >= 0; i--){
            var pos = posArr[i];
            if( this.alivePosArr.indexOf(pos) >= 0 || pos < oldPos){
                continue;
            }
            
            if( oldPos == pos ){
                return pos;
            }
            
            // 找到击退位置时,将两个位置的数据交换
            var role = this.roles[pos];
            this.roles[pos] = this.roles[oldPos]; 
            this.roles[pos]['pos'] = pos;
            if( role ) {
                role.pos = oldPos;
            }
            this.roles[oldPos] = role;

            this.alivePosArr.remove(oldPos);
            this.alivePosArr.push(pos);
            
            var rid = this.team[pos];
            this.team[pos] = this.team[oldPos];
            this.team[oldPos] = rid;
            if( rid ) {
                this.rolePoses[rid] = oldPos;
            }
            
            var nowPosRid = this.team[pos];
            if( nowPosRid ) {
                this.rolePoses[nowPosRid] = pos;
            }

            return pos;
        }
        
    },

    getAtkColPos: function(defPosArr){
        var column = defPosArr[0] % 3;
        var posArr = colSequence[column];

        for( var i = 0, len = posArr.length; i < len; i++){
            var pos = posArr[i];
            
            if( this.alivePosArr.indexOf(pos) < 0){
                continue;
            }

            if( defPosArr[0] == pos ){
                continue;
            }

            defPosArr.push(pos);
        }
    },

    getAtkLastPos: function(defPosArr){
        var column = defPosArr[0] % 3;
        var posArr = colSequence[column];

        for( var i = posArr.length -1;  i >= 0; i--){
            var pos = posArr[i];

            if( this.alivePosArr.indexOf(pos) < 0){
                continue;
            }

            if( defPosArr[0] == pos ){
                break;
            }

            defPosArr.pop();
            defPosArr.push(pos);
            break;
        }
    },

    getAtkAllPos: function(defPosArr){
        for( var pos = 0; pos < 9; pos++){
            if( this.alivePosArr.indexOf(pos) < 0){
                continue;
            }

            if( defPosArr[0] == pos ){
                continue;
            }

            defPosArr.push(pos);
        }
        
    },
    
    removeOneFromBufs : function( role, name ){
        if( name in role.bufs){
            delete role.bufs[name];
            return true;
        }

        return false;
    },

    addOneToBufs : function(role, name, contents ){
        role.bufs[name] = {};
        for( var property in contents){
            role.bufs[name][property] = contents[property];
        }
    },

    randOneFriendPos : function(atkPos){
        var weights = {};
        var len = this.alivePosArr.length;
        for( var i = 0 ; i < len; i++){
            var pos = this.alivePosArr[i];
            if( atkPos == pos){
                continue; 
            }
            
            var column = pos%3; 
            if( undefined === weights[column] ){
                weights[column] = pos;    
            }else{
                if( pos > weights[column] ){
                    continue;
                }
                weights[column] = pos;
            }
        }
        
        return weights[common.wRand(weights)];
    },

    isAllDead : function(){
        return (this.alive > 0) ? 0 : 1;
    },

    findDefendPos : function(pos){
        var defendPos = -1;
        var column = pos % 3;
        var seq = searchSequence[column];

        for( var i=0, max=seq.length; i < max; i++){
            var tempPos = seq[i];
            var rid = this.team[tempPos];
            
            if( !rid ){
                continue;
            }

            var role = this.roles[tempPos];
            if( roleStatusMap.DEAD == role.statusArr[0] ) {
                continue;
            }

            defendPos = tempPos;
            break;
        }

        return defendPos;
    },

    findAttackPos : function( pos, curRound ){
        for( ; pos < 9; pos++) {
            var rid = this.team[pos];

            if( !rid ){
                continue;
            }
            
            var role = this.roles[pos];
            if( roleStatusMap.DEAD == role.statusArr[0] ){
                continue;
            }

            if( curRound == role.round){
                continue;
            }

            role.round = curRound;
            break;
        }

        return pos;
    },

    getPetAction: function(defender, petSkillId, curRound){
        var action = {
            'atk' : 0 , 
            'atk_pos' : -1,
            'def_pos' : [],
            'atk_status' : { },
            'def_status' : { },
            'skill' : 0,
            'isself': 0,
        };
        action.atk = this.isAttacker ? (0) : (1);
        action.skill = petSkillId; 
        
        var petSkillLevel = this.pet.skillLevels[petSkillId];
        var petSkillConf = gConfPetSkillEffect[petSkillId][petSkillLevel];
        if( !petSkillConf ) return; 
        
        var skillEffectParam = petSkillConf.Param;

        if( 103 == petSkillId ) {
            // 减对方随机2人的怒气
            var defPosArr = defender.alivePosArr.slice();
            var randomDefPosArr = []; 
            for( var i = 0, len = Math.min(defPosArr.length, 2); i < len; i++ ) {
                var pos = common.randArray(defPosArr);
                randomDefPosArr.push(pos); 
                defPosArr.remove(pos);
            }

            action.def_pos = randomDefPosArr;
            
            for( var i = 0 , len = action.def_pos.length; i < len; i++){
                var pos = action.def_pos[i];
                var role = defender.roles[pos];
                var diffPower = role.statusArr[4] - skillEffectParam;

                role.statusArr[4]  = (diffPower < 0) ? 0 : diffPower;
                action.def_status[pos] = role.statusArr.slice();
                action.def_status[pos][1] = 0;
                action.def_status[pos][3] = 0;
                action.def_status[pos][5] = 0;
            }
        } else if (106 == petSkillId) {
            var defAliveRoles = [];
            var defPosArr = defender.alivePosArr.slice();
            for (var i = 0, len = defPosArr.length; i < len; ++i) {
                defAliveRoles.push(defender.roles[defPosArr[i]]);
            }

            var atkAliveRoles = [];
            var atkPosArr = this.alivePosArr.slice();
            for (var i = 0, len = atkPosArr.length; i < len; ++i) {
                atkAliveRoles.push(this.roles[atkPosArr[i]]);
            }
            
            // 守方按士气降序排序
            defAliveRoles.sort(function(a, b) {
                return b.statusArr[4] - a.statusArr[4];
            });

            // 攻方按士气升序排序
            atkAliveRoles.sort(function(a, b) {
                return a.statusArr[4] - b.statusArr[4];
            });
            
            // 减少守方士气最高的2名武将士气
            action.def_pos = [];
            var defAffectedCount = Math.min(defAliveRoles.length, 2);
            for (var i = 0; i < defAffectedCount; ++i) {
                var role = defAliveRoles[i];
                var pos = role.pos;
                role.statusArr[4] = Math.max(0, role.statusArr[4] - skillEffectParam);
                
                action.def_pos.push(pos);
                action.def_status[pos] = role.statusArr.slice();
                action.def_status[pos][1] = 0;
                action.def_status[pos][3] = 0;
                action.def_status[pos][5] = 0;
            }

            // 增加守方士气最低的2名武将士气
            action.atk_pos = [];
            var atkAffectedCount = Math.min(atkAliveRoles.length, defAffectedCount);
            for (var i = 0; i < atkAffectedCount; ++i) {
                var role = atkAliveRoles[i];
                var pos = role.pos;
                role.statusArr[4] += skillEffectParam;
                
                action.atk_pos.push(pos);
                action.atk_status[pos] = role.statusArr.slice();
                action.atk_status[pos][1] = 0; 
                action.atk_status[pos][3] = 0; 
                action.atk_status[pos][5] = 0; 
            }

        }else {
            action.isself = 1;
            var atkAlivePosArr = this.alivePosArr.slice();
            var skillEffect = {
                'param' : skillEffectParam,
                'damage' : 0,
                'round' : petSkillConf.Round,
                'isSelf' : petSkillConf.IsSelf,
                'isActive' : 0, 
            };   

            if( 102 == petSkillId ) {
                // 随机给己方2人加怒气 
                var atkPosArr = this.alivePosArr.slice();
                var randomAtkPosArr = []; 
                for( var i = 0, len = Math.min(atkPosArr.length, 2); i < len; i++ ) {
                    var pos = common.randArray(atkPosArr);
                    randomAtkPosArr.push(pos); 
                    atkPosArr.remove(pos);
                }

                for( var i = 0, len = randomAtkPosArr.length; i < len; i++ ) {
                    var pos = randomAtkPosArr[i];
                    var role = this.roles[pos];
                    role.statusArr[4] += skillEffectParam;
                             
                    action.atk_status[pos] = role.statusArr.slice();
                    action.atk_status[pos][1] = 0; 
                    action.atk_status[pos][3] = 0; 
                    action.atk_status[pos][5] = 0; 
                }

            }else if( 101 ==  petSkillId ) {
                // 随机给己方2人加提高伤害buf
                var atkPosArr = this.alivePosArr.slice();
                var randomAtkPosArr = []; 
                for( var i = 0, len = Math.min(atkPosArr.length, 2); i < len; i++ ) {
                    var pos = common.randArray(atkPosArr);
                    randomAtkPosArr.push(pos); 
                    atkPosArr.remove(pos);
                }

                for( var i = 0, len = randomAtkPosArr.length; i < len; i++ ) {
                    var pos = randomAtkPosArr[i];
                    var role = this.roles[pos];
                    this.addOneToBufs(role, 'improvehurt', skillEffect);    
                    action.atk_status[pos] = role.statusArr.slice();
                    action.atk_status[pos][1] = 0; 
                    action.atk_status[pos][3] = 0; 
                    action.atk_status[pos][5] = 0; 
                }
            }else if( 104 == petSkillId ) {
                // 随机给己方3人加怒气 
                var atkPosArr = this.alivePosArr.slice();
                var randomAtkPosArr = []; 
                for( var i = 0, len = Math.min(atkPosArr.length, 3); i < len; i++ ) {
                    var pos = common.randArray(atkPosArr);
                    randomAtkPosArr.push(pos); 
                    atkPosArr.remove(pos);
                }

                for( var i = 0, len = randomAtkPosArr.length; i < len; i++ ) {
                    var pos = randomAtkPosArr[i];
                    var role = this.roles[pos];
                    role.statusArr[4] += skillEffectParam;
                             
                    action.atk_status[pos] = role.statusArr.slice();
                    action.atk_status[pos][1] = 0; 
                    action.atk_status[pos][3] = 0; 
                    action.atk_status[pos][5] = 0; 
                }
            }else if( 105 == petSkillId ) {
                // 随机复活一人 
                // 找到已经死去英雄的位置数组
                var deadPosArr = [];
                for( var pos in this.team ) {
                    if( !this.team[pos] ) {
                        continue;
                    }

                    if( atkAlivePosArr.indexOf(+pos) >= 0 ) {
                        continue;
                    } 

                    deadPosArr.push(+pos);
                }

                if( deadPosArr.length <= 0 ) {
                    return action; 
                }

                var rebornRolePos = +common.randArray(deadPosArr);  
                var rebornRole = this.roles[rebornRolePos];
                rebornRole.bufs = {};
                rebornRole.round = curRound - 1;

                var rebornHealth = rebornRole.health * skillEffectParam / 100;
                rebornRole.statusArr = [1, 0, rebornHealth, 0, 400, 0];
                this.teamHealth += rebornHealth;
                this.alive += 1;
                this.alivePosArr.push(rebornRolePos);

                action.atk_status[rebornRolePos] = [1, 0, rebornHealth, rebornHealth, 400, 0];
            } else if (107 == petSkillId) {
                // 增加己方全员n士气和x%攻击，持续1回合
                var alivePosArr = this.alivePosArr;
                for (var i = 0, len = alivePosArr.length; i < len; ++i) {
                    var pos = alivePosArr[i];
                    var role = this.roles[pos];
                    if (!role) continue;

                    this.addOneToBufs(role, 'improvehurt', skillEffect);
                    role.statusArr[4] += (petSkillConf.Damage || 0);
                    action.atk_status[pos] = role.statusArr.slice();
                    action.atk_status[pos][1] = 0; 
                    action.atk_status[pos][3] = 0; 
                    action.atk_status[pos][5] = 0; 
                }
            }
        }

        return action;
    },

    removePetSkillBufs : function() {
    
        for( var i = 0, len = this.alivePosArr.length; i < len; i++ ) {
            var pos = this.alivePosArr[i]; 
            var role = this.roles[pos];
            
            for( var j = 0, max = petSkillEffectBufs.length; j < max; j++ ) {
                var petSkillEffect = petSkillEffectBufs[j] 
                if( !role.bufs[petSkillEffect] ) {
                    continue; 
                }
                
                role.bufs[petSkillEffect].round -= 1;

                if( 0 == role.bufs[petSkillEffect].round ) {
                    this.removeOneFromBufs(role, petSkillEffect);
                }
            }
        }

    },

    getRoleById : function(roleId) {
        var pos = this.rolePoses[roleId];
        if (null == pos) {
            return null;
        }
        return this.roles[pos];
    },

    getRoleSkillValue : function(role, effect, attr) {
        if (!role) {
            return 0;
        }

        var skillInfo = role.skills[effect];
        if (!skillInfo) {
            return 0;
        }

        return skillInfo[attr] || 0;
    },

    getRoleIdSkillValue : function(roleId, effect, attr) {
        return this.getRoleSkillValue(this.getRoleById(roleId), effect, attr);
    },

    getRoleSkillParam : function(role, effect) {
        return this.getRoleSkillValue(role, effect, 'param');
    },

    getRoleIdSkillParam : function(roleId, effect) {
        return this.getRoleIdSkillValue(roleId, effect, 'param');
    },

    getRoleSkillDamage : function(role, effect) {
        return this.getRoleSkillValue(role, effect, 'damage');
    },

    getRoleIdSkillDamage : function(roleId, effect) {
        return this.getRoleIdSkillValue(roleId, effect, 'damage');
    },

	isRoleExistBufs: function() {
		var role = arguments[0];
		var bufs = role.bufs;

        for (var i = 1; i < arguments.length; ++i) {
            var key = arguments[i];
			var buf = bufs[key];
			if (buf) {
				return true;
			}
        }

        return false;
    },

    getRoleHoroscopeValue: function(role, effectName) {
        var horoscope = role.horoscope;
        if (!horoscope) {
            return 0;
        }

        return horoscope[effectName] || 0;
    },

    getTotalHoroscopeValue: function(effectName) {
        var value = 0;
        var roles = this.roles;
        for (var pos in roles) {
            var role = roles[pos];
            if (role) {
                value += this.getRoleHoroscopeValue(role, effectName);
            }
        }
        return value;
    },

    //执行技能对参战单元属性的影响
    doSkillAddAttributes : function(defender) {
        var mdefenceRate = 0;
        var healthRate = 0;
        var addCritdamage = 0;

        if (this.SpecRoleOfDianWei) {
            mdefenceRate += this.getRoleIdSkillParam(this.SpecRoleOfDianWei, specRoleMap.DianWei.godSkill);
        }

        if (defender.SpecRoleOfDiaoChan) {
            healthRate -= defender.getRoleIdSkillParam(defender.SpecRoleOfDiaoChan, specRoleMap.DiaoChan.godSkill);
        }

        if (this.SpecRoleOfLuoShen) {
            healthRate += this.getRoleIdSkillParam(this.SpecRoleOfLuoShen, specRoleMap.LuoShen.godSkill);
        }
        
        if (defender.SpecRoleOfHuaTuo) {
            mdefenceRate -= defender.getRoleIdSkillParam(defender.SpecRoleOfHuaTuo, specRoleMap.HuaTuo.lordSkill);
        }

        for (var pos in this.roles) {
            var role = this.roles[pos];

            if (healthRate) {
                var addHealth = Math.floor(role.health * healthRate/100);
                if (this.healthBreakable) {
                    role.health += addHealth;
                }
                
                var curHealth = role.statusArr[2];
                var realAddHealth = 0;
                if (addHealth < 0) {
                    realAddHealth = Math.max(addHealth, -curHealth);
                } else {
                    realAddHealth = Math.min(addHealth, role.health - curHealth);
                }
                role.statusArr[2] += realAddHealth;
                this.teamHealth += realAddHealth;
            }

            var mdefence = Math.floor(role.mdefence * (1 + mdefenceRate/100));
            role.mdefence = mdefence;
            role.baseMdefence = mdefence;
        }
    },

    //溅射伤害
    doSkillActionSplash : function(action, defender, atkRole, defPosArr, splashRate) {
        if (0 == splashRate) {
            return;
        }

        var diffDefenderTeamHealth = 0; 
        for( var i = 0, len = defPosArr.length; i < len; i++ ) {
            diffDefenderTeamHealth += defender.roles[defPosArr[i]].statusArr[3];
        }

        var splashDamage = Math.floor(diffDefenderTeamHealth * (splashRate/100));
        var defAlivePosArr = defender.alivePosArr.slice();
        for( var i = 0, len = defAlivePosArr.length; i < len; i++ ) {
            var pos = defAlivePosArr[i];
            if( defPosArr.indexOf(pos) >= 0 ) {
                continue; 
            }

            var defRole = defender.roles[pos];
            var defStatusArr = defRole.statusArr;
            if (defStatusArr[3] < 0) {
                continue;
            }

            var roleSplashDamage = splashDamage;
            var restrainSplash = defRole.RestrainSplash;
            if (restrainSplash) {
                roleSplashDamage = Math.floor(roleSplashDamage * (1 - restrainSplash/100));
            }
            
            defender.addRoleHealthInFight(defRole, roleSplashDamage);

            action.def_status[pos] = defRole.statusArr.slice();
            action.def_pos.push(pos);
        }
    },
    
    //吸血
    doSkillActionSuck : function(action, defender, atkRole, rate) {
        if (rate <= 0) {
            return;
        }

        var totalDamage = 0;
        for (var pos in action.def_status) {
            totalDamage += action.def_status[pos][3];
        }

        if (totalDamage >= 0) {
            return;
        }

        var atkRoleStatus = atkRole.statusArr;
        if (atkRoleStatus[2] >= atkRole.health) {
            return;
        }

        var suckHealth = Math.min(atkRole.health - atkRoleStatus[2], -totalDamage*rate/100);
        this.addRoleHealthInFight(atkRole, suckHealth);
        
        action.atk_status[this.rolePoses[atkRole.id]] = atkRoleStatus.slice();
    },
    
    //加BUF技能
    doSkillActionAddBuf : function(action, role, bufName, param, round) {
        if (0 == param || round <= 0) {
            return;
        }

        var roleStatus = role.statusArr;
        var bufs = role.bufs;
        if (roleStatusMap.DEAD == roleStatus[0]) {
            return;
        }

        //已经有该buf时不替换，直接返回
        if (bufs.hasOwnProperty(bufName) && bufs[bufName]['round'] > 0) {
            return;
        }

        switch (bufName)
        {
        case 'improveatk':
        {
            var addAttack = Math.floor(role.baseAttack*param/100);
            if(bufs.hasOwnProperty('atktransdef') && bufs['atktransdef']['round'] > 0) {
                role.attack = addAttack;
            } else {
                role.attack = role.baseAttack + addAttack;
            }
            break;
        }
        case 'sleep':
        {
            if (Math.random() >= param/100) {
                return;
            }

            if (bufs.hasOwnProperty('confuse')) {
                this.removeOneFromBufs(role, 'confuse');
            }

            roleStatus[0] = roleStatusMap.SLEEP;
            break;
        }
        default:
            return;   
        };

        var bufContents = {};
        bufContents['param'] = param;
        bufContents['damage'] = 0;
        bufContents['round'] = round;
        bufContents['isSelf'] = 1;
        bufContents['isActive'] = 0;
        bufContents['layer'] = BufLayerLevel.STICK;
        this.addOneToBufs(role, bufName, bufContents);
    },
    
    //降低对对方士气
    doSkillActionReduceMorale : function(action, defender, defRole, rate, value) {
        if ((0 == rate) || (Math.random() >= rate/100)) {
            return;
        }

        defRole.statusArr[4] = Math.max(0, defRole.statusArr[4] - value);
        action.def_status[defender.rolePoses[defRole.id]] = defRole.statusArr.slice();
    },
    
    //攻击一条直线上的敌人，后排目标所受伤害逐渐递减为前一个的z%
    doSkillActionDecreaseCol: function(action, defender, value) {
        var defPosArr = action.def_pos;
        if (!defPosArr || !defPosArr.length) {
            return;
        }

        var defPos = +defPosArr[0];
        var defStatus = action.def_status[defPos];
        if (!defStatus) {
            return;
        }

        var colPosArr = colSequence[defPos % 3];
        var damage = defStatus[3];
        for (var i = 0, len = colPosArr.length; i < len; ++i) {
            var pos = colPosArr[i];
            if (pos <= defPos) {
                continue;
            }

            var role = defender.roles[pos];
            if (!role || (roleStatusMap.DEAD == role.statusArr[0])) {
                continue;
            }

            if (action.def_status[pos]) {
                continue;
            }

            damage = Math.floor(damage*value/100);
            defender.addRoleHealthInFight(role, damage);
            action.def_status[pos] = role.statusArr.slice();
            action.def_pos.push(pos);
        }
    },
    
    //一次攻击结束后处理函数
    doActionFinish: function(action, defender, atkRole) {
        var atkStatusArr = atkRole.statusArr;

        if (roleStatusMap.DEAD == atkStatusArr[0]) {
            return;
        }

        var defDeadCount = 0;
        for (var pos in action.def_status) {
            if (roleStatusMap.DEAD == action.def_status[pos][0]) {
                defDeadCount++;
            }
        }
        
        if (defDeadCount > 0) {
            //星座效果-犒赏, 击杀武将后回复士兵
            var hsKillRecover = this.getRoleHoroscopeValue(atkRole, 'KillRecover');
            if (hsKillRecover) {
                this.addRoleHealthInFight(atkRole, Math.floor(atkRole.health * hsKillRecover/100));
            }

            //星座效果-奋勇, 击杀武将后额外回复士气
            var hsKillEmbraved = this.getRoleHoroscopeValue(atkRole, 'KillEmbraved');
            if (hsKillEmbraved) {
                atkStatusArr[4] += hsKillEmbraved;    
            }

            action.atk_status[atkRole.pos] = atkStatusArr.slice();
        }
    },

    getRoleActiveSkillEffect : function( role ) {
        // 获取英雄装备的主动技能效果 
        var effect = '';
        for( var property in role.skills){
            // 当技能为主动技能时
            if( role.skills[property]['isActive'] ){
                effect = property;
                break;
            }
        }
        
        return effect;
    },
}

exports.Fighter = Fighter;
